﻿using System;
using System.ServiceModel.Description;
using Newtonsoft.Json.Serialization;
using UFIDA.U9.Cust.Pub.WS.ProxyService.Json;
using UFIDA.U9.WSS.ProxyService.AccessProxy;
using UFIDA.U9.WSS.ProxyService.Behavior.WebHttp.Base;
using UFIDA.U9.WSS.ProxyService.Exceptions;
using UFIDA.U9.WSS.ProxyService.Json;
using UFIDA.U9.WSS.ProxyService.Utils;
using UFSoft.UBF;

namespace UFIDA.U9.WSS.ProxyService.Behavior.WebHttp
{
    public class ProxyServiceDispatchFormatter : NewtonsoftJsonDispatchFormatter
    {
        private readonly bool _accessProxy;
        private readonly bool _useDataContract;

        public ProxyServiceDispatchFormatter(OperationDescription operation, bool useDataContract = false,
            bool accessProxy = false) : base(operation)
        {
            _useDataContract = useDataContract;
            _accessProxy = accessProxy;
        }

        protected override void ParseParameters(byte[] rawBody, object[] parameters)
        {
            IContractResolver resolver = new ProxyBaseContractResolver(_useDataContract);
            Type proxyType = GetProxyTypeFromRawBody(rawBody, resolver);
            if (proxyType == null)
                throw new WSException(ExceptionCodes.ProxyServiceProxyTypePropertyIsIncorrect,
                    "proxy is incorrect");
            parameters[0] =
                JsonHelper.GetJsonPropertyValue(rawBody, proxyType, Constant.DataPropertyName, resolver);
        }

        /// <summary>
        ///     获取代理类型
        /// </summary>
        /// <param name="rawBody"></param>
        /// <param name="resolver"></param>
        /// <returns></returns>
        private Type GetProxyTypeFromRawBody(byte[] rawBody, IContractResolver resolver)
        {
            string proxyString =
                JsonHelper.GetJsonPropertyValue<string>(rawBody, Constant.ProxyTypePropertyName, resolver);
            if (string.IsNullOrWhiteSpace(proxyString))
                throw new WSException(ExceptionCodes.ProxyServiceProxyTypePropertyIsEmpty,
                    "proxy is empty");
            //Proxy是否需要授权
            if (_accessProxy)
            {
                bool isAccess = AccessProxyManager.Instance.IsAccess(proxyString);
                if (!isAccess)
                    throw new WSException(ExceptionCodes.ProxyServiceProxyAccessDenied,
                        "proxy access denied");
            }

            try
            {
                return TypeManager.TypeLoader.LoadType(proxyString);
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
                throw new WSException(ExceptionCodes.ProxyServiceProxyTypePropertyIsIncorrect,
                    "proxy is incorrect", ex);
            }
        }

        /// <summary>
        ///     获取代理对象
        /// </summary>
        /// <param name="rawBody"></param>
        /// <param name="proxyType"></param>
        /// <param name="resolver"></param>
        /// <returns></returns>
        private object GetProxyObjectFromRawBody(byte[] rawBody, Type proxyType, IContractResolver resolver)
        {
            return JsonHelper.GetJsonPropertyValue(rawBody, proxyType, Constant.ProxyTypePropertyName, resolver);
        }

        protected override IContractResolver GetSerializeReplyContractResolver()
        {
            return new ProxyBaseContractResolver(_useDataContract);
        }
    }
}